💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    03 Todo 목록 화면 및 뷰 상세 설명 | ✅저자: 이유정(박사)

    ✅ 3. Todo 목록 화면 및 뷰 상세 설명

    1️⃣ 목록을 보여주는 뷰: TodoListView

    todo/ views.py
    
    class TodoListView(LoginRequiredMixin, ListView):
        model = Todo
        template_name = "todo/todo_list.html"
        context_object_name = "todos"
        paginate_by = 5
    
        def get_queryset(self):
            queryset = Todo.objects.filter(author=self.request.user)
    
            # 🔍 검색 필터
            query = self.request.GET.get("q")
            if query:
                queryset = queryset.filter(name__icontains=query)
    
            # ✅ 완료 상태 필터
            complete_filter = self.request.GET.get("complete")
            if complete_filter == "complete":
                queryset = queryset.filter(complete=True)
            elif complete_filter == "incomplete":
                queryset = queryset.filter(complete=False)
    
            # 📊 정렬 옵션
            sort = self.request.GET.get("sort")
            if sort == "exp":
                queryset = queryset.order_by("-exp")
            elif sort == "complete_date":
                queryset = queryset.order_by("-completed_at")
            else:
                queryset = queryset.order_by("-created_at")  # 기본 정렬
    
            return queryset
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context["query"] = self.request.GET.get("q", "")
            context["complete_filter"] = self.request.GET.get("complete", "")
            context["sort"] = self.request.GET.get("sort", "")
            return context
    

    🔎 기능 요약

    • 로그인한 사용자(author)의 할 일만 가져옴
    • 검색어로 필터링
    • 완료 여부로 필터링
    • 정렬 옵션 제공 (생성일, 경험치, 완료일 등)
    • 페이지네이션 기능 탑재 (5개씩)

    2️⃣ 템플릿: todo/templates/todo/todo_list.html

    🧩 기본 구조

    {% extends "todo/include/base.html" %}
    {% block title %}할일 목록{% endblock %}
    
    • 전체 레이아웃은 base.html을 상속
    • 검색 필터, 추가 버튼, 목록 카드, 페이징, 삭제 모달 등 포함

    🔍 검색/필터/정렬 폼

    <form method="get">
      <input type="search" name="q" value="{{ query }}" ...>
      <select name="complete">...</select>
      <select name="sort">...</select>
      <button type="submit">검색</button>
    </form>
    
    • q, complete, sort 값을 통해 뷰에서 필터링 적용됨

    ➕ 새 할일 버튼

    <a href="{% url 'todo:todo_create' %}">새 할 일</a>
    

    ✅ 목록 카드 UI

    {% for todo in todos %}
      <div>
        <h2><a href="{% url 'todo:todo_detail' todo.id %}">{{ todo.name }}</a></h2>
        <p>{{ todo.description }}</p>
        <a href="{% url 'todo:todo_update' todo.id %}">수정</a>
        <button onclick="openDeleteModal({{ todo.id }})">삭제</button>
        <form id="delete-form-{{ todo.id }}" method="post">...</form>
      </div>
    {% empty %}
      <p>할 일이 없습니다.</p>
    {% endfor %}
    

    📄 페이징

    {% if page_obj.has_previous %}<a href="?page=...">이전</a>{% endif %}
    <span>페이지 {{ page_obj.number }} / {{ page_obj.paginator.num_pages }}</span>
    {% if page_obj.has_next %}<a href="?page=...">다음</a>{% endif %}
    
    • ListView의 페이징 객체를 이용한 UI

    🗑 삭제 모달

    • 삭제 버튼 클릭 시 모달이 뜨고, JS로 삭제 폼을 제출
    <script>
    function openDeleteModal(id) { ... }
    function confirmDelete() { ... }
    </script>
    

    3️⃣ 연계 URL

    # todo/urls.py
    path("", TodoListView.as_view(), name="todo_list")
    
    • /todo/로 접속 시 todo_list.html이 렌더링됨

    ✅ 전체 흐름 요약

    1. 사용자가 /todo/ 접속
    2. TodoListView가 로그인 사용자에 맞는 할일 목록 필터링
    3. 검색/필터/정렬 기능이 URL 파라미터로 적용됨
    4. todo_list.html에서 할 일 목록을 카드 형태로 표시
    5. 수정/삭제/상세 보기로 각각 링크 연결됨
    6. 삭제는 JS 모달을 통해 안전하게 처리

    Tip: get_queryset()으로 로직을 분기하므로, 나중에 조건부 필터/검색/정렬을 자유롭게 커스터마이징 가능!

    TOP
    preload preload